package Serialization_Deserialization;/*
 *
 * @author 陈粒
 * @version 创建时间：2021/7/16 20:00
 */
/**
 * Java序列化与反序列化：
 * Java序列化是指把Java对象转换为字节序列的过程；而Java反序列化是指把字节序列恢复为Java对象的过程。
 *
 * 如何实现Java序列化与反序列化：
 * 序列化：
 * java.io.ObjectOutputStream：表示对象输出流
 * 它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化，把得到的字节序列写到一个目标输出流中。
 * 反序列化：
 * java.io.ObjectInputStream：表示对象输入流
 * 它的readObject()方法源输入流中读取字节序列，再把它们反序列化成为一个对象，并将其返回。
 *
 * 实现序列化的要求：
 * 只有实现了Serializable或Externalizable接口的类的对象才能被序列化，否则抛出异常。
 *
 * JDK类库中序列化的步骤：
 * 步骤一：创建一个对象输出流，它可以包装一个其它类型的目标输出流，如文件输出流：
 * ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“D:\\objectfile.obj”));
 * 步骤二：通过对象输出流的writeObject()方法写对象：
 * out.writeObject(“Hello”);
 * out.writeObject(new Date());
 *
 * JDK类库中反序列化的步骤
 * 步骤一：创建一个对象输入流，它可以包装一个其它类型输入流，如文件输入流：
 * ObjectInputStream in = new ObjectInputStream(new fileInputStream(“D:\\objectfile.obj”));
 * 步骤二：通过对象输出流的readObject()方法读取对象：
 * String obj1 = (String)in.readObject();
 * Date obj2 = (Date)in.readObject();
 * 
 * 说明：为了正确读取数据，完成反序列化，必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。
 * 特别注意：
 * 因为序列化和反序列化都是基于二进制流的，也就是说，
 * 序列化其实就是将Student的相关信息转化为二进制存储在了Student.obj这个文件中，那么用文本编辑器打开查看的话当然是会出现乱码的。
 * 只有通过反序列化才能将存储的二进制读取出来，然后正常显示在控制台上。
 */

import java.io.*;
//把Student类的对象序列化到文件中，并从该文件中反序列化，向console(控制台)显示结果。
public class Student implements Serializable {//Student类
    //Student类的属性
    private String name;
    private char sex;
    private int year;
    private double gpa;

    public Student() {
    }

    public Student(String name, char sex, int year, double gpa) {
        this.name = name;
        this.sex = sex;
        this.year = year;
        this.gpa = gpa;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public double getGpa() {
        return gpa;
    }

    public void setGpa(double gpa) {
        this.gpa = gpa;
    }

    public static void main(String[] args) {
        Student st = new Student("陈", '男', 1999, 2);//创建Student类的对象，并给有参构造函数赋值
        File file = new File("C:\\Users\\tarena\\Desktop\\file\\Serializablefile.txt");//用来序列化时存储对象转换的字节序列的文件
        serializable_deserializable(file,st);
    }
    public static void serializable_deserializable(File file, Student st) {
        try {
            try {
                file.createNewFile();//创建Serializablefile.txt文件，没有就创建，有就不创建
            } catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            try {
                //序列化,把对象转换为字节序列
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(st);
                oos.flush();
                oos.close();
                fos.close();
                //反序列化，把字节序列恢复为对象
                FileInputStream fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                Student t2 = (Student) ois.readObject();
                //打印Student类对象的属性值
                System.out.println("name:" + t2.getName());
                System.out.println("sex:" + t2.getSex());
                System.out.println("year:" + t2.getYear());
                System.out.println("gpa:" + t2.getGpa());
                ois.close();
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}